package com.easylinkin.linkappapi.ruleengine.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easylinkin.linkappapi.intelligentrule.entity.IntelligentRuleExpression;
import com.easylinkin.linkappapi.intelligentrule.mapper.IntelligentRuleExpressionMapper;
import com.easylinkin.linkappapi.linkage.entity.LinkageConfigRelateServiceParm;
import com.easylinkin.linkappapi.linkage.mapper.LinkageConfigRelateServiceParmMapper;
import com.easylinkin.linkappapi.openapi.event.DeviceUnitVersionUpdateEvent;
import com.easylinkin.linkappapi.ruleengine.entity.DataFlush;
import com.easylinkin.linkappapi.ruleengine.entity.RuleExecution;
import com.easylinkin.linkappapi.ruleengine.entity.RuleTrigger;
import com.easylinkin.linkappapi.ruleengine.mapper.DataFlushServiceMapper;
import com.easylinkin.linkappapi.ruleengine.service.DataFlushService;
import com.easylinkin.linkappapi.ruleengine.service.RuleEngineService;
import com.easylinkin.linkappapi.ruleengine.service.RuleExecutionService;
import com.easylinkin.linkappapi.ruleengine.service.RuleTriggerService;
import com.easylinkin.linkappapi.tenant.entity.TenantRefDeviceUnit;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Resource;
import org.apache.commons.lang3.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

/**
 * <p>
 * 数据清洗 刷新
 * </p>
 *
 * @author TongJie
 * @since 2020-08-24
 */
@Component
public class DataFlushServiceImpl extends ServiceImpl<DataFlushServiceMapper, DataFlush> implements DataFlushService {


    private static final Logger LOGGER = LoggerFactory.getLogger(DataFlushServiceImpl.class);
    @Resource
    private RuleTriggerService ruleTriggerService;
    @Resource
    private RuleEngineService ruleEngineService;
    @Resource
    private RuleExecutionService ruleExecutionService;
    @Resource
    private IntelligentRuleExpressionMapper intelligentRuleExpressionMapper;
    @Resource
    private LinkageConfigRelateServiceParmMapper linkageConfigRelateServiceParmMapper;

    @Async
    @EventListener
    public void onApplicationEvent(DeviceUnitVersionUpdateEvent deviceUnitVersionUpdateEvent) {
        LOGGER.info("接收到型号更新事件");
        Map<String, List<TenantRefDeviceUnit>>  message = (Map<String, List<TenantRefDeviceUnit>> ) deviceUnitVersionUpdateEvent.getSource();
        List<TenantRefDeviceUnit> tenantRefDeviceUnitAddList = message.get("add");
        List<TenantRefDeviceUnit> tenantRefDeviceUnitDeleteList = message.get("delete");
        Assert.notNull(tenantRefDeviceUnitAddList,"租户关联型号add列表为null");
        Assert.notNull(tenantRefDeviceUnitDeleteList,"租户关联型号delete列表为null");
        Set<String> actualAddedTenantRefDeviceUnitIds = new HashSet<>();
//        比较 add 和 delete 的找出 实际新增或修改的
        for (TenantRefDeviceUnit addTenantRefDeviceUnit : tenantRefDeviceUnitAddList) {
            for (TenantRefDeviceUnit deleteTenantRefDeviceUnit : tenantRefDeviceUnitDeleteList) {
                if (deleteTenantRefDeviceUnit.getTenantId().equals(addTenantRefDeviceUnit.getTenantId()) && deleteTenantRefDeviceUnit.getDeviceUnitId().equals(addTenantRefDeviceUnit.getDeviceUnitId())) {
                    break;
                }
                actualAddedTenantRefDeviceUnitIds.add(addTenantRefDeviceUnit.getId());
            }
        }
        if (ObjectUtils.isEmpty(actualAddedTenantRefDeviceUnitIds)) {
            LOGGER.info("实际对租户关联型号的对象的修改为空，不用刷规则引擎部分的数据");
            return;
        }
        flushDeviceUnitDataDifferentFromTenantRefDeviceUnitGlobal(actualAddedTenantRefDeviceUnitIds);

    }


    /**
     * 刷数据用接口：解决型号更新了 但是业务数据关联仍然是旧的设备型号id 导致不能回显问题，以及推断不能正常工作
     *
     * 涉及要更新的表 4个： rule_trigger  / rule_execution / linkage_config_relate_service_parm/ linkapp_intelligent_rule_expression
     * <p>device_unit_id>: rule_trigger  / rule_execution/linkage_config_relate_service_parm </p>
     * <p>device_attribute_id>: linkapp_intelligent_rule_expression </p>
     * <p>device_attribute_parent_id>: linkapp_intelligent_rule_expression </p>
     * <p>device_service_id>: linkage_config_relate_service_parm</p>
     * <p>device_parm_id>: linkage_config_relate_service_parm</p>
     * @param actualAddedTenantRefDeviceUnitIds  只需要查找并更新的范围限定  租户关联型号表的id集合
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> flushDeviceUnitDataDifferentFromTenantRefDeviceUnitGlobal(Set<String> actualAddedTenantRefDeviceUnitIds) {
        Map result = new HashMap();

        flushRuleTriggersWhenDeviceUnitUpdate(result, actualAddedTenantRefDeviceUnitIds);

        flushExecutionsWhenDeviceUnitUpdate(result, actualAddedTenantRefDeviceUnitIds);

        flushConfigRelateParmsWhenDeviceUnitUpdate(result, actualAddedTenantRefDeviceUnitIds);

        LOGGER.info("flushDeviceUnitDataDifferentFromTenantRefDeviceUnitGlobal 调用结果是： {}", result);

        return result;
    }

    void flushRuleExpressionWhenDeviceUnitUpdate(Map result) {
// 查询需要刷 deviceAttrId的 规则表达式
        List<IntelligentRuleExpression> intelligentRuleExpressions = baseMapper.getDeviceAttrIdErrorCanCorrectRuleExpressions();
        result.put("修改deviceAttrId前 intelligentRuleExpressions", JSONArray.parseArray(JSONArray.toJSONString(intelligentRuleExpressions), IntelligentRuleExpression.class));
        for (IntelligentRuleExpression intelligentRuleExpression : intelligentRuleExpressions) {
            intelligentRuleExpression.setDeviceAttributeId(intelligentRuleExpression.getNewDeviceAttributeId());
            intelligentRuleExpressionMapper.updateById(intelligentRuleExpression);
        }
        result.put("修改deviceAttrId后 intelligentRuleExpressions", intelligentRuleExpressions);
// 查询需要刷 deviceAttrParentId的 规则表达式
        List<IntelligentRuleExpression> intelligentRuleExpressions2 = baseMapper.getDeviceParentAttrIdErrorCanCorrectRuleExpressions();
        result.put("修改deviceAttrParentId前 intelligentRuleExpressions", JSONArray.parseArray(JSONArray.toJSONString(intelligentRuleExpressions2), IntelligentRuleExpression.class));
        for (IntelligentRuleExpression intelligentRuleExpression : intelligentRuleExpressions2) {
            intelligentRuleExpression.setDeviceAttributeParentId(intelligentRuleExpression.getNewDeviceAttributeParentId());
            intelligentRuleExpressionMapper.updateById(intelligentRuleExpression);
        }
        result.put("修改deviceAttrParentId后 intelligentRuleExpressions", intelligentRuleExpressions2);

    }

    void flushRuleTriggersWhenDeviceUnitUpdate(Map result, Set<String> actualAddedTenantRefDeviceUnitIds) {
        //        查询能被刷的触发器
        List<RuleTrigger> ruleTriggerList = baseMapper.getDeviceUnitIdErrorCanCorrectRuleTriggers(actualAddedTenantRefDeviceUnitIds);
        result.put("修改前 ruleTriggerList", JSONArray.parseArray(JSONArray.toJSONString(ruleTriggerList), RuleTrigger.class));
        for (RuleTrigger ruleTrigger : ruleTriggerList) {
            ruleTrigger.setDeviceUnitId(ruleTrigger.getNewDeviceUnitId());
            ruleTriggerService.updateById(ruleTrigger);
        }
        result.put("修改后 ruleTriggerList", ruleTriggerList);

        flushRuleExpressionWhenDeviceUnitUpdate(result);
    }

    void flushExecutionsWhenDeviceUnitUpdate(Map result, Set<String> actualAddedTenantRefDeviceUnitIds) {
        //查询能被刷的执行器：
        List<RuleExecution> ruleExecutions = baseMapper.getDeviceUnitIdErrorCanCorrectRuleExecutions(actualAddedTenantRefDeviceUnitIds);
        result.put("修改前ruleExecutions", JSONArray.parseArray(JSONArray.toJSONString(ruleExecutions), RuleExecution.class));
        for (RuleExecution ruleExecution : ruleExecutions) {
            ruleExecution.setDeviceUnitId(ruleExecution.getNewDeviceUnitId());
            ruleExecutionService.updateById(ruleExecution);
        }
        result.put("修改后ruleExecutions", ruleExecutions);
    }

    public void flushConfigRelateParmsWhenDeviceUnitUpdate(Map result, Set<String> actualAddedTenantRefDeviceUnitIds) {
        List<LinkageConfigRelateServiceParm> linkageConfigRelateServiceParmList = baseMapper.selectDeviceUnitIdErrorCanCorrectConfigRelateServiceParmList(actualAddedTenantRefDeviceUnitIds);
        result.put("修改前的linkageConfigRelateServiceParmList", JSONArray.parseArray(JSONArray.toJSONString(linkageConfigRelateServiceParmList), LinkageConfigRelateServiceParm.class));
//        更新型号id
        for (LinkageConfigRelateServiceParm linkageConfigRelateServiceParm : linkageConfigRelateServiceParmList) {
            linkageConfigRelateServiceParm.setDeviceUnitId(linkageConfigRelateServiceParm.getNewDeviceUnitId());
            linkageConfigRelateServiceParm.setDeviceServiceId(linkageConfigRelateServiceParm.getNewDeviceServiceId());
            linkageConfigRelateServiceParm.setDeviceParmId(linkageConfigRelateServiceParm.getNewDeviceParmId());
            linkageConfigRelateServiceParmMapper.updateById(linkageConfigRelateServiceParm);
        }
        result.put("修改后 linkageConfigRelateServiceParmList", linkageConfigRelateServiceParmList);
    }

    /**
     * 刷数据用接口
     */
    @Override
    public Map<String, Object> clearIntelligentExpressionSortAndLogicDataGlobal() {
        QueryWrapper qw = new QueryWrapper();
        qw.select("id");
        List<RuleTrigger> ruleTrigger = ruleTriggerService.list();
        for (RuleTrigger trigger : ruleTrigger) {
            qw = new QueryWrapper();
            qw.eq("rule_trigger_id", trigger.getId());
            qw.orderByAsc("sort_no");
            List<IntelligentRuleExpression> expressions = intelligentRuleExpressionMapper.selectList(qw);
            updateIntelligentExpressionSortAndLogicDataGlobal(expressions);
        }
        return new Hashtable<>();
    }

    private void updateIntelligentExpressionSortAndLogicDataGlobal(List<IntelligentRuleExpression> expressions) {
        if (ObjectUtils.isEmpty(expressions)) {
            return;
        }
        if (expressions.size() == 1) {
            for (IntelligentRuleExpression expression : expressions) {
                expression.setSortNo(1);
                expression.setLogicCode(null);

            }
        } else {
            for (int i = 0; i < expressions.size(); i++) {
                IntelligentRuleExpression expression = expressions.get(i);
                expression.setSortNo(i + 1);
            }
            if (expressions.get(0).getLogicCode() == null) {
                for (int i = 0; i + 1 < expressions.size(); i++) {
                    IntelligentRuleExpression expression = expressions.get(i);
                    expression.setLogicCode(expressions.get(i + 1).getLogicCode());
                }
                expressions.get(expressions.size() - 1).setLogicCode(null);
            }
        }

        for (IntelligentRuleExpression expression : expressions) {
            System.out.println("表达式>：" + expression.getId() + ",triggerId: " + expression.getRuleTriggerId() + " sort: " + expression.getSortNo() + ", logic: " + expression.getLogicCode());
            intelligentRuleExpressionMapper.updateById(expression);
        }
    }

}

